using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Drawing;
using System.Windows.Forms;

using SBPweb.Modules.Modularity;
using SBPweb.Modules.Smartparts;
using SBPweb.Modules.ChatController.Controls;
using SBPweb.Localization;
using SBPweb.Contracts;
using SBPweb.Contracts.ChatController;
using SBPweb.Contracts.Messaging;
using SBPweb.Controls.Windows.Editors.HelperClasses;
using SBPweb.Contracts.Options;
using SBPweb.Contracts.Implementation;

using Verety.SharedMeta.UIMeta.Common;
using Verety.SharedMeta.DirectoryServiceMeta;
using Verety.SharedMeta.MessagingServiceMeta.Conversation;

// This alias is needed for the module loader to recognize the module's entry point
[assembly: AssemblyDefaultAlias("SBPweb.Modules.ChatController.ChatControllerModule")]

namespace SBPweb.Modules.ChatController
{
    internal struct ChatControlPositionInfo
    {
        public Point FloatingLocation;
        public Size FloatingSize;
        public AppearanceStyle InitialAppearanceStyle;
        public DockStyle InitialDockStyle;
    }

    public class ChatControllerModule : ModuleBase, IChatControllerService, IService
	{
		#region Private members

		private ModuleLoader mModuleLoader;
        private ImageCollection mSmileys = new ImageCollection();
        private List<ChatControl> mChatControls = new List<ChatControl>();
        private IOptionsService mOptionsService;
        private ChatOptionsControl mChatOptionsControl;
        private ChatControlPositionInfo mChatControlPositionInfo = new ChatControlPositionInfo();

		#endregion

		#region Public members

		public System.Collections.IDictionary Smileys
        {
            get
            {
                return mSmileys;
            }
            set
            {
                mSmileys = value as ImageCollection;
            }
        }

        public ChatConfiguration ChatConfiguration
        {
            get
            {
                return mChatOptionsControl.ChatConfiguration;
            }
        }

		#region IChatControllerModule Members

		public bool OpenOpenedChatWithThisContact(string user, string route)
		{
			foreach (ChatControl c in mChatControls)
			{
				if (c.Conversation is IConference)
				{
					continue;
				}
				string contact = c.Conversation.Partner.User + "@" + c.Conversation.Partner.Server + "/" + c.Conversation.Partner.Resource;
				if (contact == user && c.Conversation.RouteAddress == route)
				{
					if (c.ParentForm == Host)
					{
						c.Parent.Select();
					}
					else
					{
						c.ParentForm.Focus();
					}
					return true;
				}
			}
			return false;
		}

		#endregion

		#region IService Members

		public IModule Module
		{
			get
			{
				return this;
			}
		}

		#endregion

		#endregion

		#region Internal members

		internal Control InvokeControl
        {
            get
            {
                return (Host as Control);
            }
		}

		#endregion

		#region Constructor logic

		public ChatControllerModule(IModuleHost host)
            : base(host)
        {
            pIcon = SBPweb.Modules.ChatController.Properties.Resources.Contacts;
            Name = "SBPweb.Modules.ChatController";
            mModuleLoader = host.ModuleLoader;

            mSmileys = new ImageCollection();

			mSmileys.Add(":R", SBPweb.Modules.ChatController.Properties.Resources.respect);
			mSmileys.Add(":U", SBPweb.Modules.ChatController.Properties.Resources.eyes);
			mSmileys.Add(":)", SBPweb.Modules.ChatController.Properties.Resources.smiley01);
			mSmileys.Add(";)", SBPweb.Modules.ChatController.Properties.Resources.smiley02);
			mSmileys.Add(":(", SBPweb.Modules.ChatController.Properties.Resources.smiley03);
			mSmileys.Add(":D", SBPweb.Modules.ChatController.Properties.Resources.smiley04);
			mSmileys.Add(":P", SBPweb.Modules.ChatController.Properties.Resources.smiley05);
			mSmileys.Add(":$", SBPweb.Modules.ChatController.Properties.Resources.smiley06);
			mSmileys.Add(":o", SBPweb.Modules.ChatController.Properties.Resources.smiley07);
			mSmileys.Add(":=", SBPweb.Modules.ChatController.Properties.Resources.smiley08);
			mSmileys.Add(":[", SBPweb.Modules.ChatController.Properties.Resources.smiley09);
			mSmileys.Add(":\\", SBPweb.Modules.ChatController.Properties.Resources.smiley10);
			mSmileys.Add(";(", SBPweb.Modules.ChatController.Properties.Resources.smiley11);
			mSmileys.Add(">:", SBPweb.Modules.ChatController.Properties.Resources.smiley12);
			mSmileys.Add(":]", SBPweb.Modules.ChatController.Properties.Resources.smiley13);
            mSmileys.Add("[fck]", SBPweb.Modules.ChatController.Properties.Resources.undoc01);

		}

		#endregion

		#region Overridden methods

		public override void Initialize()
        {
            if (HostType != ModuleHostType.WindowsForms)
            {
				Host.LogManager.WriteError(this, "The HostType is not WinForms!", "ChatController");
                return;
            }

			Services.Add(typeof(IChatControllerService), this);

            IMessagingService ms = Services.Get<IMessagingService>();
			if (ms != null)
			{
				(ms.ManagedDirectoryServiceObject as IDirectoryService).Conversations.OnConversationRequested -= new ConversationRequestedHandler(Conversations_OnConversationRequested);
				(ms.ManagedDirectoryServiceObject as IDirectoryService).Conversations.OnConversationClosed -= new ConversationClosedHandler(Conversations_OnConversationClosed);
				ms.OnAutenticate -= new ConnectionHandler(ChatControllerModule_OnAutenticate);
				ms.OnDisconnect -= new ConnectionHandler(ChatControllerModule_OnDisconnect);

				(ms.ManagedDirectoryServiceObject as IDirectoryService).Conversations.OnConversationRequested += new ConversationRequestedHandler(Conversations_OnConversationRequested);
				(ms.ManagedDirectoryServiceObject as IDirectoryService).Conversations.OnConversationClosed += new ConversationClosedHandler(Conversations_OnConversationClosed);
				ms.OnAutenticate += new ConnectionHandler(ChatControllerModule_OnAutenticate);
				ms.OnDisconnect += new ConnectionHandler(ChatControllerModule_OnDisconnect);
			}

            mOptionsService = this.Services.Get<IOptionsService>();
            mOptionsService.OnApply -= new EventHandler(OptionsService_OnApply);
			mOptionsService.OnApply += new EventHandler(OptionsService_OnApply);

            mChatOptionsControl = new ChatOptionsControl(this, mOptionsService);

			(new LocalizationExtender()).SetResourceKey(mChatOptionsControl, "Title");
            LocalizationExtender.OnInvalidatingControls -= new EventHandler(LocalizationExtender_OnInvalidatingControls);
			LocalizationExtender.OnInvalidatingControls += new EventHandler(LocalizationExtender_OnInvalidatingControls);

            LoadPersistency();

            IsInitialized = true;
        }

        public override void Terminate()
        {
			IsInitialized = false;

			SavePersistency();

			if (Services.ContainsKey(typeof(IChatControllerService)))
			{
				Services.Remove(typeof(IChatControllerService));
			}

			IMessagingService ms = Services.Get<IMessagingService>();
			if (ms != null)
			{
				(ms.ManagedDirectoryServiceObject as IDirectoryService).Conversations.OnConversationRequested -= new ConversationRequestedHandler(Conversations_OnConversationRequested);
				(ms.ManagedDirectoryServiceObject as IDirectoryService).Conversations.OnConversationClosed -= new ConversationClosedHandler(Conversations_OnConversationClosed);
				ms.OnAutenticate -= new ConnectionHandler(ChatControllerModule_OnAutenticate);
				ms.OnDisconnect -= new ConnectionHandler(ChatControllerModule_OnDisconnect);
			}
			LocalizationExtender.OnInvalidatingControls -= new EventHandler(LocalizationExtender_OnInvalidatingControls);
			mOptionsService.OnApply -= new EventHandler(OptionsService_OnApply);

			mChatOptionsControl.Dispose();
			mChatOptionsControl = null;

			mOptionsService.RemoveOptionsTab("Chat");
			
			while (mChatControls.Count > 0)
            {
                mChatControls[0].Conversation.Close();
                mChatControls.RemoveAt(0);
            }
		}

		#region Persistency

		public override void SavePersistency()
        {
            IStatePersistenceService persistenceService = Services.Get<IStatePersistenceService>();
            if (persistenceService != null)
            {
                PersistencyDictionary state = persistenceService.Load(this);

                state.SetInt("FloatingLocationX", mChatControlPositionInfo.FloatingLocation.X);
                state.SetInt("FloatingLocationY", mChatControlPositionInfo.FloatingLocation.Y);
                state.SetInt("FloatingSizeW", mChatControlPositionInfo.FloatingSize.Width);
                state.SetInt("FloatingSizeH", mChatControlPositionInfo.FloatingSize.Height);
                state.SetInt("InitialAppearanceStyle", (int)mChatControlPositionInfo.InitialAppearanceStyle);
                state.SetInt("InitialDockStyle", (int)mChatControlPositionInfo.InitialDockStyle);

                mChatOptionsControl.SavePersistence(state);
                persistenceService.Save(this, state);
                Host.LogManager.WriteVerbose(this, "Persistency saved for chat module.", "ChatController");
            }
        }

        public override void LoadPersistency()
        {
            IStatePersistenceService persistenceService = Services.Get<IStatePersistenceService>();
            if (persistenceService != null)
            {
                PersistencyDictionary state = persistenceService.Load(this);

                mChatControlPositionInfo.FloatingLocation = new Point(state.GetInt("FloatingLocationX", 0), state.GetInt("FloatingLocationY", 0));
                mChatControlPositionInfo.FloatingSize = new Size(state.GetInt("FloatingSizeW", 30), state.GetInt("FloatingSizeH", 400));
                mChatControlPositionInfo.InitialAppearanceStyle = (AppearanceStyle)state.GetInt("InitialAppearanceStyle", 0);
                mChatControlPositionInfo.InitialDockStyle = (DockStyle)state.GetInt("InitialDockStyle", 0);

                mChatOptionsControl.LoadPersistence(state);
                mChatOptionsControl.Smileys = Smileys;
                Host.LogManager.WriteVerbose(this, "Persistency loaded for chat module.", "ChatController");
            }
		}

		#endregion

		#endregion

		#region Event handlers

		private void ChatControllerModule_OnDisconnect(object sender)
        {
            while (mChatControls.Count>0)
            {
                mChatControls[0].Conversation.Close();
            }

            if (mOptionsService != null)
            {
                try
                {
                    mOptionsService.RemoveOptionsTab("Chat");
                }
                catch (NullReferenceException)
                {
                }
                catch (Exception ex)
                {
					Host.LogManager.WriteInfo(this, "Cannot remove chat tab from options. " + ex.Message, "ChatController");
                }
            }
        }

        private void ChatControllerModule_OnAutenticate(object sender)
        {
            try
            {
                mOptionsService.AddOptionsTab("Chat", LocalizationExtender.GetString(mChatOptionsControl, "Title"), mChatOptionsControl);
            }
            catch (Exception ex)
            {
				Host.LogManager.WriteInfo(this, "Cannot add chat tab from options. " + ex.Message, "ChatController");
			}
        }

        private void OptionsService_OnApply(object sender, EventArgs e)
        {
			if (IsInitialized)
			{
				SavePersistency();
			}
        }

        private void LocalizationExtender_OnInvalidatingControls(object sender, EventArgs e)
        {
            mOptionsService.RenameOptionsTab("Chat", LocalizationExtender.GetString(mChatOptionsControl, "Title"));
        }

        private delegate void Conversations_OnConversationClosedHandler(Verety.SharedMeta.MessagingServiceMeta.IMessagingService messenger, IConversation conversation, IConversationClosedArgs args);
        private void Conversations_OnConversationClosed(Verety.SharedMeta.MessagingServiceMeta.IMessagingService messenger, IConversation conversation, IConversationClosedArgs args)
        {
            if (InvokeControl.InvokeRequired)
            {
                InvokeControl.Invoke(new Conversations_OnConversationClosedHandler(Conversations_OnConversationClosed), messenger, conversation, args);
                return;
            }
            ChatControl _cc = null;
            foreach (ChatControl cc in mChatControls)
            {
                if (cc.Conversation.Equals(conversation))
                {
                    _cc = cc;
                }
            }
            if (_cc != null)
            {
                if (mChatControls.Count == 1)
                {
                    try
                    {
                        if (!(_cc.DockControlInstance as Control).IsDisposed)
                            mChatControlPositionInfo = _cc.ChatControlClosingInfo;
                    }
                    catch (System.ObjectDisposedException ode)
                    { 
                        //Do NOTHING!!!
                    }
                }

                mChatControls.Remove(_cc);
                Host.Smartparts.Remove(_cc);
            }
        }

        private delegate void Conversations_OnConversationRequestedHandler(Verety.SharedMeta.MessagingServiceMeta.IMessagingService messenger, IConversation conversation, IConversationRequestedArgs args);
        private void Conversations_OnConversationRequested(Verety.SharedMeta.MessagingServiceMeta.IMessagingService messenger, IConversation conversation, IConversationRequestedArgs args)
        {
            if (InvokeControl.InvokeRequired)
            {
                InvokeControl.Invoke(new Conversations_OnConversationRequestedHandler(Conversations_OnConversationRequested), messenger, conversation, args);
                return;
            }
            if (!args.ReCreate)
            {
                string name;

                if (conversation is IConference)
                {
                    name = string.Format("{0}:{1}", conversation.RouteAddress, (conversation as IConference).Conference.Name);
                }
                else
                {
                    bool ourconversation = messenger.Connection.UserContactId.Equals(conversation.Requester);

                    name = string.Format("{0}:{1}", conversation.RouteAddress, ourconversation ? conversation.Receiver.Name : conversation.Requester.Name);
                }

                ChatControl cc = new ChatControl(conversation as IConversation, this, messenger as IDirectoryService, mChatControlPositionInfo);

                mChatControls.Add(cc);
                Host.Smartparts.Add(cc);
            }

        }

        #endregion
	}
}
